
package com.hlkj.pay.controller.order;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.pay.app.common.IDownloadExcelService;
import com.hlkj.pay.app.order.IPayOrderAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.controller.BaseController;
import com.hlkj.pay.dto.common.OrderStatusDto;
import com.hlkj.pay.dto.order.OrderPageStatisticsDto;
import com.hlkj.pay.dto.order.PayOrderQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.fund.MerchantFundAccountBindDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.service.merchant.IMerchantFundAccountService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.vo.order.req.MerAcctPayOrderParamReq;
import com.hlkj.pay.vo.order.req.OrderAccount;
import com.hlkj.pay.vo.order.req.PayOrderPageQueryReq;
import com.hlkj.pay.vo.order.resp.PageOrderAndStatisticsResp;
import com.hlkj.pay.vo.order.resp.PayOrderDetailResp;
import com.hlkj.pay.vo.order.resp.export.PayOrderFileExport;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;

/**
 * @author HlpayTeam
 * @date 2024/10/23 11:36
 */
@Tag(name = "支付订单管理")
@RestController
@RequestMapping("/v1/order/pay")
@RequiredArgsConstructor
@Slf4j
public class PayOrderController extends BaseController {

    private final IPayOrderService payOrderService;

    private final IPayOrderAppService payOrderAppService;

    private final IDownloadExcelService downloadExcelService;

    private final IMerchantFundAccountService merchantFundAccountService;

    @Operation(summary = "订单查询")
    @GetMapping("/page")
    CommonResult<PageOrderAndStatisticsResp> queryPayOrderPage(PayOrderPageQueryReq payOrderPageQueryReq) {
        PageOrderAndStatisticsResp pageOrderAndStatisticsResp = null;
        // 是否平台订单号
        boolean platformNo = false;
        PayOrderQueryDto payOrderQueryDto = BeanUtil.copy(payOrderPageQueryReq, PayOrderQueryDto.class);
        if (payOrderPageQueryReq.getType() != null && StringUtils.hasText(payOrderPageQueryReq.getOrderNo())) {
            // 1:平台订单号 2:商户订单号 3:机构订单号 4:渠道订单号 5:渠道附加订单号
            switch (payOrderPageQueryReq.getType()) {
                case 1:
                    payOrderQueryDto.setPayOrderNo(payOrderPageQueryReq.getOrderNo());
                    platformNo = true;
                    break;
                case 2:
                    payOrderQueryDto.setMchOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 3:
                    payOrderQueryDto.setInsOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 4:
                    payOrderQueryDto.setChannelOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 5:
                    payOrderQueryDto.setChannelOrderId(payOrderPageQueryReq.getOrderNo());
                    break;
            }
        }

        // 平台订单号 去掉时间查询
        if(platformNo){
            payOrderPageQueryReq.setStartTime(null);
            payOrderPageQueryReq.setEndTime(null);
            payOrderPageQueryReq.setRangeTime(null);
        }else{
            if (!StringUtils.hasText(payOrderPageQueryReq.getStartTime()) || !StringUtils.hasText(payOrderPageQueryReq.getEndTime())) {
                return CommonResult.error(CommonResultCode.ORDER_STATISTICS_TIME_NOT_EMPTY);
            }
            if (DateUtils.betweenDay(payOrderPageQueryReq.getStartTime(), payOrderPageQueryReq.getEndTime()) > 90) {
                String format = String.format(CommonResultCode.ORDER_DAY_STATISTICS_ERROR.getMsg(), "90");
                return CommonResult.error(CommonResultCode.ORDER_DAY_STATISTICS_ERROR.getCode(), format);
            }
        }

        processQueryDate(payOrderPageQueryReq, payOrderQueryDto);
        // processQuerySn(payOrderPageQueryReq, payOrderQueryDto);
        PageResult<PayOrderDO> page = payOrderService.queryPage(payOrderQueryDto);
        List<PayOrderDO> list = page.getList();
        if (CollectionUtils.isEmpty(list)) {
            CommonResult<PageResult<PayOrderDetailResp>> result = buildPageResult(page, Collections.emptyList());
            pageOrderAndStatisticsResp = cn.hutool.core.bean.BeanUtil.copyProperties(result.getData(), PageOrderAndStatisticsResp.class);
            pageOrderAndStatisticsResp.setOrderStatisticsDO(new OrderPageStatisticsDto());
            return CommonResult.success(pageOrderAndStatisticsResp);
        }

        if (payOrderPageQueryReq.getExport() == 1) {
            String fileName = payOrderPageQueryReq.getExportName();
            if (!StringUtils.hasText(fileName)) fileName = "订单导出_" + DateUtils.getDateString(DatePattern.PURE_DATETIME_PATTERN);
            downloadExcelService.createExcel(fileName, payOrderQueryDto, PayOrderFileExport.class);
            return CommonResult.success();
        } else {
            List<PayOrderDetailResp> payOrderRespList = cn.hutool.core.bean.BeanUtil.copyToList(list, PayOrderDetailResp.class);
            payOrderRespList.stream().forEach(payOrderDetailResp -> {
                payOrderDetailResp.setSn(payOrderDetailResp.getOrderSn());
            });
            payOrderAppService.processOrderStatusQuery(list);
            processOrderList(payOrderRespList);
            processOrderAccessList(payOrderRespList);
            CommonResult<PageResult<PayOrderDetailResp>> result = buildPageResult(page, payOrderRespList);
            pageOrderAndStatisticsResp = cn.hutool.core.bean.BeanUtil.copyProperties(result.getData(), PageOrderAndStatisticsResp.class);
            pageOrderAndStatisticsResp.setOrderStatisticsDO(payOrderService.queryStaticOrdersPage(payOrderQueryDto));
            return CommonResult.success(pageOrderAndStatisticsResp);

        }
    }

    @Operation(summary = "订单查询")
    @GetMapping("/batchQuery")
    CommonResult<PageResult<MerAcctPayOrderParamReq>> batchQuery(PayOrderPageQueryReq payOrderPageQueryReq) {
        // 是否平台订单号
        boolean platformNo = false;
        PayOrderQueryDto payOrderQueryDto = BeanUtil.copy(payOrderPageQueryReq, PayOrderQueryDto.class);
        if (payOrderPageQueryReq.getType() != null && StringUtils.hasText(payOrderPageQueryReq.getOrderNo())) {
            // 1:平台订单号 2:商户订单号 3:机构订单号 4:渠道订单号 5:渠道附加订单号
            switch (payOrderPageQueryReq.getType()) {
                case 1:
                    payOrderQueryDto.setPayOrderNo(payOrderPageQueryReq.getOrderNo());
                    platformNo = true;
                    break;
                case 2:
                    payOrderQueryDto.setMchOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 3:
                    payOrderQueryDto.setInsOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 4:
                    payOrderQueryDto.setChannelOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 5:
                    payOrderQueryDto.setChannelOrderId(payOrderPageQueryReq.getOrderNo());
                    break;
            }
        }

        // 平台订单号 去掉时间查询
        if(platformNo){
            payOrderPageQueryReq.setStartTime(null);
            payOrderPageQueryReq.setEndTime(null);
            payOrderPageQueryReq.setRangeTime(null);
        }else{
            if (!StringUtils.hasText(payOrderPageQueryReq.getStartTime()) || !StringUtils.hasText(payOrderPageQueryReq.getEndTime())) {
                return CommonResult.error(CommonResultCode.ORDER_STATISTICS_TIME_NOT_EMPTY);
            }
            if (DateUtils.betweenDay(payOrderPageQueryReq.getStartTime(), payOrderPageQueryReq.getEndTime()) > 90) {
                String format = String.format(CommonResultCode.ORDER_DAY_STATISTICS_ERROR.getMsg(), "90");
                return CommonResult.error(CommonResultCode.ORDER_DAY_STATISTICS_ERROR.getCode(), format);
            }
        }

        processQueryDate(payOrderPageQueryReq, payOrderQueryDto);
        // processQuerySn(payOrderPageQueryReq, payOrderQueryDto);
        List<MerAcctPayOrderParamReq> merAcctPayOrderParamReqList = new ArrayList<>();
        PageResult<PayOrderDO> page = payOrderService.queryPage(payOrderQueryDto);
        List<PayOrderDO> list = page.getList();
        if (CollectionUtils.isEmpty(list)) {
            CommonResult<PageResult<MerAcctPayOrderParamReq>> result = buildPageResult(page, merAcctPayOrderParamReqList);
            return result;
        }
        MerAcctPayOrderParamReq merAcctPayOrderParamReq = null;
        for(PayOrderDO payOrderDO:list){
            merAcctPayOrderParamReq = new MerAcctPayOrderParamReq();
            merAcctPayOrderParamReq.setPayOrderNo(payOrderDO.getPayOrderNo());

            List<MerchantFundAccountBindDO> merchantFundAccountBindList = merchantFundAccountService.queryAccountBindList(payOrderDO.getMchChannelCode(), CommonEnum.YES_NO_TYPE.YES,
                    CommonEnum.YES_NO_TYPE.YES);
            if (org.springframework.util.CollectionUtils.isEmpty(merchantFundAccountBindList)) {
                log.info("payAcctOrder 商户 预设默认分账数据不存在 payOrderNo:{}", payOrderDO.getPayOrderNo());
                continue;
            }
            List<OrderAccount> orderAccountList = new ArrayList<>();
            for(MerchantFundAccountBindDO merchantFundAccountBindDO:merchantFundAccountBindList){
                OrderAccount orderAccount = new OrderAccount();
                orderAccount.setAccountNo(merchantFundAccountBindDO.getAccountNo());
                orderAccount.setName(merchantFundAccountBindDO.getName());
                orderAccount.setDescription("系统分账");
                if(merchantFundAccountBindDO.getD0() == null){
                    orderAccount.setPeriodType(0);
                }else{
                    orderAccount.setPeriodType(merchantFundAccountBindDO.getD0());
                }

                if(payOrderDO.getAmount() != null && merchantFundAccountBindDO.getRate() != null){
                    orderAccount.setAmount(NumberUtil.roundStr(payOrderDO.getAmount().multiply(merchantFundAccountBindDO.getRate()).divide(new BigDecimal(100)).doubleValue(),2));
                }
                orderAccountList.add(orderAccount);
            }
            merAcctPayOrderParamReq.setAcctInfos(orderAccountList);
            merAcctPayOrderParamReqList.add(merAcctPayOrderParamReq);
        }

        return buildPageResult(page, merAcctPayOrderParamReqList);
    }

    @Operation(summary = "订单批量查询")
    @GetMapping("/batchQueryList")
    CommonResult<List<String>> batchQueryList(PayOrderPageQueryReq payOrderPageQueryReq) {
        // 是否平台订单号
        boolean platformNo = false;
        PayOrderQueryDto payOrderQueryDto = BeanUtil.copy(payOrderPageQueryReq, PayOrderQueryDto.class);
        if (payOrderPageQueryReq.getType() != null && StringUtils.hasText(payOrderPageQueryReq.getOrderNo())) {
            // 1:平台订单号 2:商户订单号 3:机构订单号 4:渠道订单号 5:渠道附加订单号
            switch (payOrderPageQueryReq.getType()) {
                case 1:
                    payOrderQueryDto.setPayOrderNo(payOrderPageQueryReq.getOrderNo());
                    platformNo = true;
                    break;
                case 2:
                    payOrderQueryDto.setMchOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 3:
                    payOrderQueryDto.setInsOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 4:
                    payOrderQueryDto.setChannelOrderNo(payOrderPageQueryReq.getOrderNo());
                    break;
                case 5:
                    payOrderQueryDto.setChannelOrderId(payOrderPageQueryReq.getOrderNo());
                    break;
            }
        }

        // 平台订单号 去掉时间查询
        if(platformNo){
            payOrderPageQueryReq.setStartTime(null);
            payOrderPageQueryReq.setEndTime(null);
            payOrderPageQueryReq.setRangeTime(null);
        }
        processQueryDate(payOrderPageQueryReq, payOrderQueryDto);
        List<PayOrderDO> list = payOrderService.queryList(payOrderQueryDto);
        List<String>  payOrderNos = new ArrayList<>();
        for(PayOrderDO payOrderDO:list){
            payOrderNos.add(payOrderDO.getPayOrderNo());
        }
        return  CommonResult.success(payOrderNos);
    }

    @Operation(summary = "订单详情")
    @GetMapping("/detail")
    CommonResult<PayOrderDetailResp> queryPayOrderDetail(@RequestParam("payOrderNo") String payOrderNo) {
        PayOrderDO payOrderDO = payOrderService.queryPayOrder(payOrderNo);
        if (payOrderDO == null) {
            return CommonResult.success(null);
        }
        PayOrderDetailResp payOrderDetailResp = BeanUtil.copyProperties(payOrderDO, PayOrderDetailResp.class);
        processOrder(payOrderDetailResp);
        return CommonResult.success(payOrderDetailResp);
    }

    @Operation(summary = "状态同步")
    @GetMapping("/status")
    CommonResult<Void> status(@RequestParam("payOrderNo") String payOrderNo) {
        OrderStatusDto orderStatusDto = new OrderStatusDto();
        orderStatusDto.setOrderNo(payOrderNo);
        orderStatusDto.setOrderStatusType(PayOrderEnums.ORDER_STATUS_TYPE.PAY_ORDER_STATUS.getCode());
        payOrderAppService.processOrderStatusQuery(orderStatusDto,false);
        return CommonResult.success();
    }

}
